home *** CD-ROM | disk | FTP | other *** search
/ Fritz: All Fritz / All Fritz.zip / All Fritz / FILES / PROGNG_C / MRUTC.LZH / RESIDENT.C < prev    next >
Text File  |  1988-01-19  |  8KB  |  318 lines

  1. /* -------- resident.c --------- */
  2.  
  3. #include <dos.h>
  4. #include <stdio.h>
  5.  
  6. static union REGS rg;
  7. static struct SREGS seg;
  8. static unsigned mcbseg;
  9. static unsigned dosseg;
  10. static unsigned dosbusy;
  11. static unsigned enddos;
  12. char far *intdta;
  13. static unsigned intsp;
  14. static unsigned intss;
  15. static char far *mydta;
  16. static unsigned myss;
  17. static unsigned stack;
  18. static unsigned ctrl_break;
  19. static unsigned mypsp;
  20. static unsigned intpsp;
  21. static unsigned pids[2];
  22. static int pidctr = 0;
  23. static int pp;
  24. static void interrupt (*oldtimer)(void);
  25. static void interrupt (*old28)(void);
  26. static void interrupt (*oldkb)(void);
  27. static void interrupt (*olddisk)(void);
  28. static void interrupt (*oldcrit)(void);
  29. extern void interrupt (*ZeroDivVector)(void);
  30. static void interrupt newtimer(void);
  31. static void interrupt new28(void);
  32. static void interrupt newkb(void);
  33. static void interrupt newdisk(int,int,int,int,int,int,int,int,int,int,int,int);
  34. static void interrupt newcrit(int,int,int,int,int,int,int,int,int,int,int,int);
  35. extern unsigned sizeprogram;
  36. extern unsigned scancode;
  37. extern unsigned keymask;
  38. static int resoff = 0;
  39. static int running = 0;
  40. static int popflg = 0;
  41. static int diskflag = 0;
  42. static int kbval;
  43. static int cflag;
  44.  
  45. static void dores(void);
  46. static void pidaddr(void);
  47. static void resterm(void);
  48. void resident_psp(void);
  49. void interrupted_psp(void);
  50. void popup(void);
  51.  
  52. /* -------- establish & declare residency --------- */
  53. void resinit()
  54. {
  55.     segread(&seg);
  56.     myss = seg.ss;
  57.     /* ------ get address of DOS busy flag ---- */
  58.     rg.h.ah = 0x34;
  59.     intdos(&rg, &rg);
  60.     dosseg = _ES;
  61.     dosbusy = rg.x.bx;
  62.     /* ----- get address of resident program's dta ----- */
  63.     mydta = getdta();
  64.     /* -------- get addresses of PID in DOS ------- */
  65.     pidaddr();
  66.     /* ----- get original interrupt vectors ----- */
  67.     oldtimer = getvect(0x1c);
  68.     old28 = getvect(0x28);
  69.     oldkb = getvect(9);
  70.     olddisk = getvect(0x13);
  71.     /* ----- attach vectors to resident program ----- */
  72.     setvect(0x1c, newtimer);
  73.     setvect(9, newkb);
  74.     setvect(0x28, new28);
  75.     setvect(0x13, newdisk);
  76.     /* ------ compute stack pointer ------- */
  77.     stack = (sizeprogram - (seg.ds - seg.cs)) * 16 - 300;
  78.     /* ---- restore zero divide interrupt vector --- */
  79.     setvect(0, ZeroDivVector);
  80.     /* ----- terminate and stay resident ------- */
  81.     rg.x.ax = 0x3100;
  82.     rg.x.dx = sizeprogram;
  83.     intdos(&rg, &rg);
  84. }
  85.  
  86. /* ------ BIOS disk functions ISR ------- */
  87. static void interrupt newdisk(bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,flgs)
  88. {
  89.     diskflag++;
  90.     (*olddisk)();
  91.     ax = _AX;        /* for the register returns */
  92.     cx = _CX;
  93.     dx = _DX;
  94.     newcrit(bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,flgs);        /* to get current flags register */
  95.     flgs = cflag;
  96.     --diskflag;
  97. }
  98.  
  99. /* -------- critical error ISR ---------- */
  100. static void interrupt newcrit(bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,flgs)
  101. {
  102.     ax = 0;
  103.     cflag = flgs;    /* for newdisk */
  104. }
  105.  
  106. /* ----- keyboard ISR ------ */
  107. static void interrupt newkb()
  108. {
  109.     if (inportb(0x60) == scancode)    {
  110.         kbval = peekb(0, 0x417);
  111.         if (!resoff && ((kbval & keymask) ^ keymask) == 0)    {
  112.             /* --- reset the keyboard ---- */
  113.             kbval = inportb(0x61);
  114.             outportb(0x61, kbval | 0x80);
  115.             outportb(0x61, kbval);
  116.             outportb(0x20, 0x20);
  117.             /* ---- set hotkey indicator ---- */
  118.             if (!running)
  119.                 popflg = 1;
  120.             return;
  121.         }
  122.     }
  123.     (*oldkb)();
  124. }
  125.  
  126. /* ----- timer ISR ------- */
  127. static void interrupt newtimer()
  128. {
  129.     (*oldtimer)();
  130.     if (popflg && peekb(dosseg, dosbusy) == 0)
  131.         if (diskflag == 0)    {
  132.             outportb(0x20, 0x20);
  133.             popflg = 0;
  134.             dores();
  135.         }
  136. }
  137.  
  138. /* ----- DOSOK ISR -------- */
  139. static void interrupt new28()
  140. {
  141.     (*old28)();
  142.     if (popflg && peekb(dosseg, dosbusy) != 0)    {
  143.         popflg = 0;
  144.         dores();
  145.     }
  146. }
  147.  
  148. /* ------ switch psp context from interrupted to TSR ----- */
  149. void resident_psp()
  150. {
  151.     /* ------ save interrupted program's psp ----- */
  152.     intpsp = peek(dosseg, *pids);
  153.     /* ----- set resident program's psp ----- */
  154.     for (pp = 0; pp < pidctr; pp++)
  155.         poke(dosseg, pids [pp], mypsp);
  156. }
  157.  
  158. /* ---- switch psp context from TSR to interrupted ---- */
  159. void interrupted_psp()
  160. {
  161.     /* ----- reset interrupted program's psp ----- */
  162.     for (pp = 0; pp < pidctr; pp++)
  163.         poke(dosseg, pids [pp], intpsp);
  164. }
  165.  
  166. /* ------ execute the resident program ------- */
  167. static void dores()
  168. {
  169.     running = 1;
  170.     disable();
  171.     intsp = _SP;
  172.     intss = _SS;
  173.     _SP = stack;
  174.     _SS = myss;
  175.     enable();
  176.     oldcrit = getvect(0x24);/* redirect critical error     */
  177.     setvect(0x24, newcrit);
  178.     rg.x.ax = 0x3300;        /* get ctrl break setting      */
  179.     intdos(&rg, &rg);
  180.     ctrl_break = rg.h.dl;
  181.     rg.x.ax = 0x3301;        /* turn off ctrl break logic   */
  182.     rg.h.dl = 0;
  183.     intdos(&rg, &rg);
  184.     intdta = getdta();        /* get interrupted dta         */
  185.     setdta(mydta);            /* set resident dta            */
  186.     resident_psp();            /* swap psps                   */
  187.     popup();                /* execute resident program    */
  188.     interrupted_psp();        /* reset interrupted psp       */
  189.     setdta(intdta);            /* reset interrupted dta       */
  190.     setvect(0x24, oldcrit);    /* reset critical error        */
  191.     rg.x.ax = 0x3301;        /* reset ctrl break            */
  192.     rg.h.dl = ctrl_break;
  193.     intdos(&rg, &rg);
  194.     disable();                /* reset interrupted stack     */
  195.     _SP = intsp;
  196.     _SS = intss;
  197.     enable();
  198.     running = 0;
  199. }
  200. /*page*/
  201. static int avec = 0;
  202.  
  203. /* ------- test to see if the program is already resident
  204.       if not, attach to an available interrupt ---------- */
  205. unsigned resident(signature, ifunc)
  206. char *signature;
  207. void interrupt (*ifunc)();
  208. {
  209.     char *sg;
  210.     unsigned df;
  211.     int vec;
  212.  
  213.     segread(&seg);
  214.     df = seg.ds-seg.cs;
  215.     for (vec = 0x60; vec < 0x68; vec++)    {
  216.         if (getvect(vec) == NULL)    {
  217.             if (!avec)
  218.                 avec = vec;
  219.             continue;
  220.         }
  221.         for (sg = signature; *sg; sg++)
  222.             if (*sg!=peekb(peek(0,2+vec*4)+df,(unsigned)sg))
  223.                 break;
  224.         if (!*sg)
  225.             return vec;
  226.     }
  227.     if (avec)
  228.         setvect(avec, ifunc);
  229.     return 0;
  230. }
  231. /*page*/
  232. /* -------- find address of PID ---------- */
  233. static void pidaddr()
  234. {
  235.     unsigned adr = 0;
  236.  
  237.     /* ------- get the current pid --------- */
  238.     rg.h.ah = 0x51;
  239.     intdos(&rg, &rg);
  240.     mypsp = rg.x.bx;
  241.     /* ----- find the end of the DOS segment ------- */
  242.     rg.h.ah = 0x52;
  243.     intdos(&rg, &rg);
  244.     enddos = _ES;
  245.     enddos = peek(enddos, rg.x.bx-2);
  246.     /* ---- search for matches on the pid in dos ---- */
  247.     while (pidctr < 2 &&
  248.             (unsigned)((dosseg<<4) + adr) < (enddos<<4))    {
  249.         if (peek(dosseg, adr) == mypsp)    {
  250.             rg.h.ah = 0x50;
  251.             rg.x.bx = mypsp + 1;
  252.             intdos(&rg, &rg);
  253.             if (peek(dosseg, adr) == mypsp+1)
  254.                 pids[pidctr++] = adr;
  255.             /* ---- reset the original pid ------ */
  256.             rg.h.ah = 0x50;
  257.             rg.x.bx = mypsp;
  258.             intdos(&rg, &rg);
  259.         }
  260.         adr++;
  261.     }
  262. }
  263. /*page*/
  264. /* ------- terminate function ----------- */
  265. static void resterm()
  266. {
  267.     void closefiles(void);
  268.  
  269.     closefiles();    /*  close TSR files */
  270.     /* ----- restore the interrupt vectors ----- */
  271.     setvect(0x1c, oldtimer);
  272.     setvect(9, oldkb);
  273.     setvect(0x28, old28);
  274.     setvect(0x13, olddisk);
  275.     setvect(avec, (void interrupt (*)()) 0);
  276.     /* ---- get the seg addr of 1st DOS MCB ---- */
  277.     rg.h.ah = 0x52;
  278.     intdos(&rg, &rg);
  279.     mcbseg = _ES;
  280.     mcbseg = peek(mcbseg, rg.x.bx-2);
  281.     /* ---- walk thru mcb chain & release memory ----- */
  282.     segread(&seg);
  283.     while (peekb(mcbseg, 0) == 0x4d)    {
  284.         if (peek(mcbseg, 1) == mypsp)    {
  285.             rg.h.ah = 0x49;
  286.             seg.es = mcbseg+1;
  287.             intdosx(&rg, &rg, &seg);
  288.         }
  289.         mcbseg += peek(mcbseg, 3) + 1;
  290.     }
  291. }
  292. /* --------- terminate the resident program --------- */
  293. void terminate()
  294. {
  295.     if (getvect(0x13) == (void interrupt (*)()) newdisk)
  296.         if (getvect(9) == newkb)
  297.             if (getvect(0x28) == new28)
  298.                 if (getvect(0x1c) == newtimer)    {
  299.                     resterm();
  300.                     return;
  301.                 }
  302.     resoff = 1;    /* another TSR is above us, merely suspend */
  303. }
  304.  
  305.  
  306. /* ------------- restart the resident program --------- */
  307. void restart()
  308. {
  309.     resoff = 0;
  310. }
  311.  
  312. /* ------- put the program on hold -------- */
  313. void wait()
  314. {
  315.     resoff = 1;
  316. }
  317.  
  318.